<?php

namespace Database\Seeders;


use App\Service\Dir;
use App\Service\Photo\Image;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use QL\QueryList;


class NewsSeeder extends Seeder
{
    //  php artisan db:seed --class=NewsSeeder
    //  sudo -u root php artisan db:seed --class=NewsSeeder

    /***
     *
     * 填充文章：
     *   1、文章详情必须在网站上去爬取，因为数据库中还有 WordPress 的标签，不知道规则，只能在原来的网站上采集
     *   2、WordPress会自动保存，自动保存的不会在页面显示，所以需要去原来的网站上访问一下，看看能不能访问到，用来区别是真实文章还是自动保存的
     *   3、将自动保存的的文章的ID，保存在一个文件中，下一次请求的时候，不用在去原来的网站上验证是否是自动保存的，这样反应速度更快
     *   4、处理 img 标签  style="max-width: 100%;"  替换  style="width: 100%;"
     *   5、图片处理： 质量变为20%
     */


    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        // 清空数据表 后在添加
        $toDb1 = DB::table('news');
        $toDb2 = DB::table('news_desc');

        // 采集的文章比较多 不一定要清空数据重新采集
        //$toDb1->truncate();
        //$toDb2->truncate();

        // 测试
        //$url = 'https://asiatechwire.com/tsmc-approves-29-6-billion-capital-budget.html';
        //$this->gather($url);

        // 整理数据
        // 有些数据要保存失败，尤其是一些文章的图片链接太古怪，页面也没有图片，也获取不到图片所以这些数据不采集图片
        //  也不保存这些数据
        $outImageIds = [11041, 11177, 1645, 1654, 1667];
        $outImageIds = [11041, 11177, 39157, 74898, 74898, 11744];
        $startNumber = 0;
        $getNumber   = 1000;
        for($ii = $startNumber; $ii < 100 * 1000; $ii = $ii + $getNumber){
            $this->showMsg('开始执行'.$ii);
            $this->runHand($ii, $getNumber, $outImageIds);
        }
    }

    // 执行
    protected function runHand($start = 0, $number = 1000, $outImageIds = [])
    {
        $time = time();
        // 查询原来的数据
        $this->showMsg('获取文章。。。。');
        $sql   = "select * from wp_posts where post_status='publish';";
        $sql   = "select * from wp_posts limit $start, $number;";
        $posts = DB::select($sql);
        $posts = json_decode(json_encode($posts), true);
        $total = count($posts);

        // 查询 阅读数量
        $this->showMsg('获取文章阅读量。。。。');
        $sql2  = "select * from wp_postmeta where meta_key='post_views_count';";
        $reads = DB::select($sql2);
        $reads = json_decode(json_encode($reads), true);
        $reads = array_column($reads, null, 'post_id');

        // 处理获取到的文章
        foreach($posts as $key => $_post){
            // 判断是否已经采集
            $_url = 'https://asiatechwire.com/'.$_post['post_name'].'.html';
            $this->showMsg('采集第'.($key + 1).'/'.$total.'篇文章：ID：'.$_post['ID'].'  '.$_url);
            $info = DB::table('news')->where('from_url', $_url)->first();
            if($info){
                $this->showMsg('    ====》采集第'.($key + 1).'/'.$total.'篇文章已经采集了，不在采集');
                continue;
            }
            if(substr($_url, -17) == '-revision-v1.html'){
                continue;
            }

            // 测试
            /*if($_post['ID'] > 10){
                die;
            }*/

            // 查询是否有详情内容
            //   将没有详情内容的ID保存在一个文件中，避免下次在去网站请求获取详情
            if($this->hasNoContentId($start, $_post['ID'])){
                $this->showMsg('    ====》采集第'.($key + 1).'/'.$total.'篇文章没有内容，不保存：在没有内容的文件中1');
                continue;
            }

            // $_post['post_name'] 有很多相同的
            // $_post['post_name'] 是否已经访问过了 如果已经访问了，则不用在继续访问
            $_sql2  = "select * from wp_posts where post_name='".$_post['post_name']."' order by id ASC limit 1;";
            $_post2 = DB::select($_sql2);
            $_post2 = json_decode(json_encode($_post2), true);
            if($this->hasNoContentId($start, $_post2[0]['ID'])){
                $this->showMsg('    ====》采集第'.($key + 1).'/'.$total.'篇文章没有内容，不保存：在没有内容的文件中2');
                $this->saveNoContentId($start, $_post['ID']);
                continue;
            }

            // 采集图片与内容
            $_noImg = in_array($_post['ID'], $outImageIds);
            if(!empty($_noImg)){
                continue;
            }

            // 采集内容，并保存图片
            $gather = $this->gather($_url, $_post['ID']);
            $_read  = $reads[$_post['ID']] ?? [];
            if(empty($gather)){
                $this->showMsg('    ====》采集第'.($key + 1).'/'.$total.'篇文章不存在：保存到没有文件的内容中1');
                $this->saveNoContentId($start, $_post['ID']);
                continue;
            }
            if(empty($gather['content'])){
                $this->showMsg('    ====》采集第'.($key + 1).'/'.$total.'篇文章没有内容，不保存：保存到没有文件的内容中2');
                $this->saveNoContentId($start, $_post['ID']);
                continue;
            }

            // 组合
            $gather['read_no']  = $_read['meta_value'] ?? 0;
            $gather['from_url'] = $_url;

            // 执行
            $_news = $this->makeNews($_post, $gather, $time);
            $_desc = $this->makeDesc($_post, $gather, $time);

            // 周末一直开机执行 为了避免程序报错 一直进行 使用 try
            /*DB::table('news')->insert($_news);
            DB::table('news_desc')->insert($_desc);
            // 更新链接
            // 完善请求链接
            $link = atwArticleLink($_post['post_title'] ?: $gather['title'], $_post['ID']);
            $info = DB::table('news')->where('link', $link)->where('id', '!=', $_post['ID'])->where('verify', '>=', 0)->first();
            if($info){
                die('该文章链接已经存在！');
            }
            DB::table('news')->where('id', $_post['ID'])->update(['link' => $link]);*/

            // 执行保存
            try{
                DB::table('news')->insert($_news);
                DB::table('news_desc')->insert($_desc);
                // 更新链接
                // 完善请求链接
                $link = atwArticleLink($_post['post_title'] ?: $gather['title'], $_post['ID']);
                $info = DB::table('news')->where('link', $link)->where('id', '!=', $_post['ID'])->where('verify', '>=', 0)->first();
                if($info){
                    throw new \Exception('该文章链接已经存在！');
                }
                DB::table('news')->where('id', $_post['ID'])->update(['link' => $link]);
            } catch(\Exception $e){
            }
        }

    }


    // 生成文章数据
    protected function makeNews($_post, $gather, $time)
    {
        $_row = [
            'id'             => $_post['ID'],
            'uid'            => $_post['post_author'],
            'en_title'       => $_post['post_title'] ?: $gather['title'],
            'cn_title'       => '',
            'tc_title'       => '',
            'en_description' => $gather['desc'],
            'cn_description' => '',
            'tc_description' => '',
            'author'         => '',
            'pic'            => $gather['pic'],  // ?
            'images'         => json_encode($gather['images']),  // ?
            'read_no'        => $gather['read_no'],  // ?
            'virtual_no'     => $gather['read_no'],  // ?
            'comment_no'     => $_post['comment_count'],
            'praise_no'      => 0,
            'collect_no'     => 0,
            'verify'         => 1,
            'ip'             => '',
            'ip_address'     => '',
            'is_top'         => 0,
            'is_draft'       => 0,
            'from_url'       => $gather['from_url'],  // ?
            'ctime'          => strtotime($_post['post_date']),
            'mtime'          => strtotime($_post['post_modified_gmt']),
        ];

        return $_row;
    }

    // 生成文章详情数据
    protected function makeDesc($_post, $gather, $time)
    {

        $_row = [
            //'id'         => $_com['comment_ID'],
            'news_id'     => $_post['ID'],
            'en_keywords' => $gather['keywords'],
            'cn_keywords' => '',
            'tc_keywords' => '',
            'en_content'  => $gather['content'],
            'cn_content'  => '',
            'tc_content'  => '',
            'ctime'       => strtotime($_post['post_modified_gmt']),
        ];

        return $_row;
    }

    // 采集内容
    protected function gather($url, $id)
    {
        // 获取本地保存的详情内容
        $res = $this->getContent($id);
        if(empty($res)){
            try{
                $query = QueryList::get($url);
            } catch(\Exception $e){
                return [];
            }

            // 获取采集的各种内容
            $_title   = $query->find('head title')->text();
            $desc     = $query->find('head meta[name=description]')->attr('content');
            $keywords = $query->find('head meta[name=keywords]')->attr('content');
            $title    = $query->find('#container .content .pagelist-left .article-title')->text();
            $content  = $query->find('#container .content .pagelist-left .article-content')->html();
            // 保存文件
            $res = ['_title' => $_title, 'desc' => $desc, 'keywords' => $keywords, 'title' => $title, 'content' => $content];
            $this->saveContent($res, $id);
        } else{
            $_title   = $res['_title'];
            $desc     = $res['desc'];
            $keywords = $res['keywords'];
            $title    = $res['title'];
            $content  = $res['content'];
        }
        if(empty($res)){
            return [];
        }


        // 取消 figure 替换图片
        /*$content = preg_replace("/<figure.*?>(.*?)<\/figure>/is", '<p style="padding: 3px 0;">'."\\1".'</p>', $content);*/
        $content = preg_replace("/<figure.*?>(.*?)<\/figure>/is", '<p>'."\\1".'</p>', $content);
        $content = preg_replace('/<[\s]*[img|IMG].*?src=[\'|"|\s]*(.+?|\ )[\'|"|\s|].*?>/is', "<img style=\"width: 100%;\" src=\"\\1\" />", $content);

        // 取消 div
        $content = preg_replace("/<div.*?>.*?<\/div>/is", '', $content);
        $content = preg_replace("/<div.*?>.*?<\/div>/is", '', $content);
        $content = str_replace("</div>", "", $content);
        $content = str_replace("\n", "", $content);
        $content = str_replace("\t", "", $content);
        $content = preg_replace('/<[p|P].*?\>/is', '<p>', $content);
        //$content = preg_replace('/<[p|P].*?\>/is', '<p style="padding: 3px 0;">', $content);

        // 删除前后空格
        $keywords = trim($keywords);
        $desc     = trim($desc);
        $_title   = trim($_title);
        $title    = trim($title);
        $content  = trim($content);

        // 保存图片
        $res    = $this->saveImge($content);
        $reslut = [
            '_title'   => $_title,
            'title'    => $title ?: $_title,
            'desc'     => $desc,
            'keywords' => $keywords ?: $title,
            'content'  => $res['content'] ?? $content,
            'pic'      => $res['pic'] ?? '',
            'images'   => $res['images'] ?? [],
        ];

        return $reslut;
    }

    // 保存图片
    protected function saveImge($content)
    {
        $dir    = new Dir();
        $ds     = DIRECTORY_SEPARATOR;
        $domain = 'http://www.asia.com/';
        $domain = env('OLD_HOST');
        if(substr($domain, -1) == '/'){
            $domain = substr($domain, 0, -1);
        }

        $oldPath = app()->basePath().$ds.'public'.$ds.'old';
        $path    = app()->basePath().$ds.'public'.$ds.'asia';
        $images  = $this->getImage4content($content);
        $to_url  = '';  // 如果没有图片
        $allImg  = [];
        foreach($images as $_url){
            // 如果图片中含有特殊符号 则不能采集
            $_form = str_replace('&amp;', '&', $_url);  // 避免获取到的图片不能展示
            if($_form != urldecode($_form)){
                // 如果图片不存在 或者保存不成功  则删除内容中的图片
                $content = $this->romoveImg($content, $_url, $_form);
                continue;
            }
            if($_url != urldecode($_url)){
                // 如果图片不存在 或者保存不成功  则删除内容中的图片
                $content = $this->romoveImg($content, $_url, $_form);
                continue;
            }


            /*var_dump($content);
            var_dump($_url);
            var_dump(urldecode($_url));
            var_dump($_url == urldecode($_url));
            var_dump(urlencode($_url));
            var_dump($_url == urlencode($_url));*/

            // 各种路径整理
            $parse  = parse_url($_form);
            $_to    = str_replace('/wp-content', '', $parse['path']);
            $_old   = $oldPath.$_to;
            $_local = $path.$_to;
            $to_url = $domain.'/asia'.$_to;

            // 保存图片到本地
            //   如果本地图片不存在 则获取
            if(!is_file($_old)){
                //  如果图片不存在 则不操作
                //$this->showMsg('——————————————————————————保存图片到本地————————————————————');
                //$this->showMsg($_old);
                try{
                    $dir->makeDir(dirname($_old));
                    $fileData = file_get_contents($_form);
                    file_put_contents($_old, $fileData);
                } catch(\Exception $e){
                    // 如果图片不存在 或者保存不成功  则删除内容中的图片
                    $to_url  = '';  // 如果没有图片
                    $content = $this->romoveImg($content, $_url, $_form);
                    continue;
                }
            }

            // 缩略图
            //   如果保存缩略图报错
            /*try{
                $_toWidth = 650;
                $file     = new \SplFileInfo($_local);
                $image    = new Image($file);
                $width    = $image->width();  // 返回图片的宽度
                $height   = $image->height();    // 返回图片的高度
                if($width > $_toWidth * 1.1){
                    $_toHeight = $height * $_toWidth / $width;
                    $image->thumb($_toWidth, $_toHeight, $image::THUMB_CENTER)->save($_local);
                }
            } catch(\Exception $e){
                continue;
            }*/

            //  修改图片质量
            try{
                $this->showMsg('处理后的图片：'.$_local);
                $res = $this->imgQuality($_old, $_local);
            } catch(\Exception $e){
                // 如果图片不存在 或者保存不成功  则删除内容中的图片
                $to_url = '';  // 如果没有图片
                var_dump($e->getMessage());
                var_dump($e->getLine());
                $content = $this->romoveImg($content, $_url, $_form);
                continue;
            }
            if($res === false){
                // 如果图片不存在 或者保存不成功  则删除内容中的图片
                $to_url  = '';  // 如果没有图片
                $content = $this->romoveImg($content, $_url, $_form);
            }

            // 替换内容
            $allImg[] = $to_url;
            $content  = str_replace($_url, $to_url, $content);
        }

        return ['content' => $content, 'pic' => $to_url, 'images' => $allImg];
    }

    // 从内容中提取图片
    protected function getImage4content($content)
    {
        //preg_match_all('/<[\s]*img.*?src=[\'|"|\s]*(.+?|\ )[\'|"|\s|>]/is', $content, $matches);
        preg_match_all('/<[\s]*[img|IMG].*?src=[\'|"|\s]*(.+?|\ )[\'|"|\s|>]/is', $content, $matches);
        $aryimg = array();
        if($matches[1]){
            for($j = 0; $j < count($matches[1]); $j++){
                // 判断是后缀，如果是表情  则不添加
                $_url = $matches[1][$j];
                $ext  = pathinfo($_url, PATHINFO_EXTENSION);
                if($ext == 'gif'){
                    continue;
                }

                $aryimg[] = $_url;
            }
        }

        return $aryimg; //$matches[1][$j][0] //返回第一个匹配的图
    }

    // 保存采集内容 方便下次直接判断，不用远程获取
    protected function saveContent($res, $id)
    {
        $path = app()->basePath().'/bak/news/'.round($id / 1000).'/';
        $file = $path.$id.'.txt';
        (new Dir())->makeDir($path);

        file_put_contents($file, json_encode($res, JSON_UNESCAPED_UNICODE));

        return true;
    }

    // 获取采集内容
    protected function getContent($id)
    {
        $path = app()->basePath().'/bak/news/'.round($id / 1000).'/';
        $file = $path.$id.'.txt';
        $res  = [];
        try{
            $res = file_get_contents($file);
            $res = json_decode($res, true);
        } catch(\Exception $e){
        }

        return $res;
    }

    // 保存没有内容的ID 方便下次直接判断，不用远程获取
    protected function saveNoContentId($start, $id)
    {
        $all  = [];
        $file = app()->basePath().'/bak/posts_no_content_'.$start.'.json';
        if(is_file($file)){
            $all = json_decode(file_get_contents($file), true);
        }

        $all[] = $id;
        file_put_contents($file, json_encode($all, JSON_UNESCAPED_UNICODE));

        return true;
    }


    // 从缓存中 判断某个ID 是否有内容
    protected function hasNoContentId($start, $id)
    {
        $all  = [];
        $file = app()->basePath().'/bak/posts_no_content_'.$start.'.json';
        if(is_file($file)){
            $all = json_decode(file_get_contents($file), true);
        }

        //$this->showMsg('没有内容的文章ID保存的文件路径：'.$file);

        return in_array($id, $all);
    }

    // 修改图片质量：服务器本地
    protected function imgQuality($imagePath, $outputPath)
    {
        // 如果图片太大，服务器不能处理
        /*$inBytes = filesize($imagePath);
        if($inBytes > 5 * 10204 * 1024){
            return false;
        }*/

        // %E4%B8%8B%E8%BD%BD-41.jpeg // 保存失败 urlencode
        // 图片太大 ，服务器内存不足
        $outs = ['63VBTDNYDZMKTDHEOVBHZF7V2I.jpg', 'YKRNUSEBRNJLROOHXAMKCUAUOE.jpg', 'WFHSUUR4N5JKJML24G6TVNXFGQ.jpg', 'X7GQY2LPCVLQ3DIX2B25Q43QPQ.jpg', 'ChMkJlhHdx-IW1e_AABahrH8st8AAYW9wIhR0AAAFqe980'];
        foreach($outs as $_out){
            if(strpos($imagePath, $_out) !== false){
                return false;
            }
        }

        // 检测文件路径是否存在
        (new Dir())->makeDir(dirname($outputPath));

        $res = true;
        // 获取原始图像信息
        list($width, $height, $type) = getimagesize($imagePath);
        // 根据图像类型创建图像资源
        switch($type){
            case IMAGETYPE_JPEG:
                $image = imagecreatefromjpeg($imagePath);
                break;
            case IMAGETYPE_PNG:
                $image = imagecreatefrompng($imagePath);
                break;
            case IMAGETYPE_GIF:
                $image = imagecreatefromgif($imagePath);
                break;
            default:
                $res = false;
                break;
        }
        // 设置图像质量（JPEG 格式为例，0 - 100）
        imagejpeg($image, $outputPath, 20);
        // 释放图像资源
        imagedestroy($image);

        return $res;
    }

    // 删除内容中的图片
    //   如果保存图片出错，则删除内容中的图片
    protected function romoveImg($content, $_url, $_form)
    {
        $_str    = '<img style="width: 100%;" src="'.$_url.'" />';
        $content = str_replace($_str, '', $content);

        $_str    = '<img style="width: 100%;" src="'.$_form.'" />';
        $content = str_replace($_str, '', $content);

        return $content;
    }


    // 展示信息
    protected function showMsg($msg)
    {
        echo $msg."\n";
    }

}
